package top.tangyh.lamp.care.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.tangyh.basic.cache.redis2.RedisOps;
import top.tangyh.basic.exception.BizException;
import top.tangyh.lamp.care.entity.*;
import top.tangyh.lamp.care.mapper.*;
import top.tangyh.lamp.care.service.BDevBindService;
import top.tangyh.basic.base.service.impl.SuperServiceImpl;
import top.tangyh.lamp.care.manager.BDevBindManager;
import top.tangyh.lamp.care.service.BEquipmentBrandService;
import top.tangyh.lamp.care.service.IcuOnlinePatientsService;
import top.tangyh.lamp.care.vo.query.BindInfoQueryVO;
import top.tangyh.lamp.care.vo.query.PatientBindInputVO;
import top.tangyh.lamp.care.vo.result.*;
import top.tangyh.lamp.care.vo.save.BDevBindSaveVO;
import top.tangyh.lamp.care.vo.save.BindInVO;
import top.tangyh.lamp.care.vo.save.UnBindInVO;
import top.tangyh.lamp.care.vo.update.BDevBindUpdateVO;
import top.tangyh.lamp.care.vo.query.BDevBindPageQuery;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static top.tangyh.lamp.common.constant.CommonConstant.BIND_EQU_HOSPITALNUMBER;
import static top.tangyh.lamp.common.constant.CommonConstant.BIND_EQU_PATIENT;

/**
 * <p>
 * 业务实现类
 * 监护仪设备绑定中间表
 * </p>
 *
 * @author zqb
 * @date 2024-07-15 16:42:41
 * @create [2024-07-15 16:42:41] [zqb] [代码生成器生成]
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class BDevBindServiceImpl extends SuperServiceImpl<BDevBindManager, Long, BDevBind> implements BDevBindService {

    private final BPatientMapper bPatientMapper;

    private final BDevDetailMapper bDevDetailMapper;
    
    private final BDevBindMapper bDevBindMapper;

    private final RedisOps redisOps;

    private  final BBindInfoMapper bBindInfoMapper;

    private final BEquipmentBrandMapper bEquipmentBrandMapper;

    private final IcuOnlinePatientsService icuOnlinePatientsService;

//    private final IcuOnlinePatientsMapper icuOnlinePatientsMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void bind(BindInVO bindInVO) {
        String hospitalNumber = bindInVO.getHospitalNumber();
        String devCode = bindInVO.getDevCode();

        IcuOnlinePatients icuOnlinePatients=icuOnlinePatientsService.getPatientByHospitalNumber(hospitalNumber);

        BPatient yxPatientPO = bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
        if (yxPatientPO == null) {
            throw new BizException("该病人不存在");
        }

        BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(devCode);
        if (yxDevDetailPO == null) {
            throw new BizException("该设备不存在");
        }

        //判断设备病人中间表中该设备是否已绑定，如已绑定执行强制换绑
        BDevBind selectByEquIdent = bDevBindMapper.selectOneByDevCode(devCode);
        if(selectByEquIdent != null){
            bDevBindMapper.deleteByDevCode(devCode);
        }

        //获取病人识别号，用于在绑定记录表中查询信息
        String patientIdent = yxPatientPO.getPatientIdent();
        //判断设备病人中间表中该病人是否已绑定，如已绑定执行强制换绑，对上面的逻辑作补充
        List<BDevBind> selectListByPatIdent = bDevBindMapper.selectListByPatIdent(patientIdent);
        BDevDetail oldDevDetail = selectListByPatIdent.stream().map(yxDevBindPO -> {
            BDevDetail selectOneDev = bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
            return selectOneDev;
        }).filter(selectOneDev ->
                yxDevDetailPO.getDevType().equals(selectOneDev.getDevType())
        ).findAny().orElse(null);
        // 不为空就删除
        if(oldDevDetail != null){
            bDevBindMapper.deleteByDevCode(oldDevDetail.getDevCode());
        }

        //添加新的绑定中间表
        BDevBind yxDevBindPO = new BDevBind();
        yxDevBindPO.setDevCode(devCode);
        yxDevBindPO.setPatientIdent(patientIdent);
        yxDevBindPO.setBindTime(System.currentTimeMillis());
        bDevBindMapper.insert(yxDevBindPO);

        // 判断该设备是否已授权,获取该设备所属的品牌和型号最大授权数量
        String brandCode = yxDevDetailPO.getBrandCode();
        String brandTypeCode = yxDevDetailPO.getBrandTypeCode();
        //  以固定的格式获取当前时间
        String date = DateUtil.formatDateTime(new Date());
//        // 获取对应的设备的最大激活数量
//        int maxNum = yxDevAuthMapper.selectNumByCode(brandCode, brandTypeCode, date);
//
//        // 判断是否超过最大绑定数量
//        if(maxNum==0){
//            throw new BizException("该设备未授权");
//        }
        // 获取绑定中间表里所有的已绑定设备的devCode
        List<BDevBind> allDevBindList = bDevBindMapper.selectList(null);
        List<String> allDevCode = allDevBindList.stream().map(BDevBind::getDevCode).collect(Collectors.toList());
        List<BDevDetail> allDevDetail = bDevDetailMapper.selectListByDevCode(allDevCode);
        // 计算和要绑定的设备同类型的已绑定的设备数量
        long currentNum = allDevDetail.stream().filter(all ->
                StringUtils.equals(brandCode, all.getBrandCode()) && StringUtils.equals(brandTypeCode, all.getBrandTypeCode())
        ).count();

//        // 判断是否超过最大绑定数量
//        if(currentNum > maxNum){
//            throw new BadRequestException("超过最大绑定数量");
//        }

        // 再次判断是否为空，不为空就删除缓存中的数据
        if(selectByEquIdent != null){
            redisOps.del(BIND_EQU_PATIENT + devCode);
            redisOps.del(BIND_EQU_HOSPITALNUMBER + devCode);
        }
        if(oldDevDetail != null){
            redisOps.del(BIND_EQU_PATIENT + oldDevDetail.getDevCode());
            redisOps.del(BIND_EQU_HOSPITALNUMBER + oldDevDetail.getDevCode());
        }
        //新绑定的数据维护到redis
        redisOps.set(BIND_EQU_PATIENT + devCode, patientIdent);
        //新绑定的数据维护到redis
        redisOps.set(BIND_EQU_HOSPITALNUMBER + devCode, hospitalNumber);
        //保存科室编号到redi
        redisOps.set("dev:bind:dept_ident:" + devCode, yxPatientPO.getDeptIdent());
        redisOps.set("dev:bind:dept_ident:" + devCode, yxPatientPO.getDeptIdent());
        //床号
        redisOps.set("dev:bind:bedNo:" + devCode, icuOnlinePatients.getBedNumber());
        //患者姓名
        redisOps.set("dev:bind:patientName:" + devCode, yxPatientPO.getPatientName());
        //病区
        redisOps.set("dev:bind:ward_code:" + devCode, yxPatientPO.getWardIdent());
    }





    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unBind(UnBindInVO unBindInVO) {
        String hospitalNumber = unBindInVO.getHospitalNumber();
        String devCode = unBindInVO.getDevCode();

        BPatient yxPatientPO = bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
        if (yxPatientPO == null) {
            throw new BizException("该病人不存在");
        }

        BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(devCode);
        if (yxDevDetailPO == null) {
            throw new BizException("该设备不存在");
        }

        //处理绑定中间表数据
        String patientIdent = yxPatientPO.getPatientIdent();
        //一定要根据病人识别号和设备识别号同时去绑定中间表查找数据，确保两者同时验证
        BDevBind yxDevBindPO = bDevBindMapper.selectOneByDevCodePatIdent(devCode, patientIdent);
        if (yxDevBindPO == null) {
            throw new BizException("绑定关系不存在");
        }
        //删除绑定中间表的数据，根据病人识别号和设备识别号作为条件删除
        bDevBindMapper.deleteByDevCodePatIdent(devCode, patientIdent);



        //删除redis中绑定关系

        redisOps.del(BIND_EQU_PATIENT + devCode);


        redisOps.del(BIND_EQU_HOSPITALNUMBER + devCode);

        redisOps.del("dev:bind:dept_ident:" + devCode);

        redisOps.del("dev:bind:bedNo:" + devCode);

        redisOps.del("dev:bind:patientName:" + devCode );
        redisOps.del("dev:bind:ward_code:" + devCode, yxPatientPO.getWardIdent());
    }

    @Override
    public PageOutputDTO<BindInfoOutputVO> selectPageListByQuery(BindInfoQueryVO bindInfoQueryVO) {
        PageHelper.startPage(bindInfoQueryVO.getPage(), bindInfoQueryVO.getSize());
        List<BindInfoOutputVO> resultList = bBindInfoMapper.selectPageListByQuery(bindInfoQueryVO);
        return PageOutputDTO.buildPageOutput(new PageInfo<>(resultList));
    }


    @Override
    public List<PatientBindOutputVO> queryPatientBind(PatientBindInputVO patientBindInputVO) {
        String patientIdent = patientBindInputVO.getPatientIdent();
        String hospitalNumber = patientBindInputVO.getHospitalNumber();

        BPatient yxPatientPO = bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
        if (yxPatientPO == null) {
            throw new BizException("该病人不存在");
        }

        List<BDevBind> yxDevBindPOList = bDevBindMapper.selectListByPatIdent(patientIdent);
        List<PatientBindOutputVO> patientBindOutputVOList = yxDevBindPOList.stream().map(yxDevBindPO -> {
            PatientBindOutputVO patientBindOutputVO = new PatientBindOutputVO();
            BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
            if(null!=yxDevDetailPO){
                patientBindOutputVO.setDevCode(yxDevDetailPO.getDevCode());
                patientBindOutputVO.setDevType(yxDevDetailPO.getDevType());
                patientBindOutputVO.setBrandTypeCode(yxDevDetailPO.getBrandTypeCode());
                patientBindOutputVO.setId(yxDevDetailPO.getId());

                BEquipmentBrand yxEquipmentBrandPO=bEquipmentBrandMapper.selectById(Long.valueOf(yxDevDetailPO.getBrand()));
                patientBindOutputVO.setBrandName(yxEquipmentBrandPO.getBrandName());
            }

            return patientBindOutputVO;
        }).collect(Collectors.toList());
        return patientBindOutputVOList;
    }

    @Override
    public List<PatientBindOutputVO> queryPatientBindFuer(PatientBindInputVO patientBindInputVO) {
        String patientIdent = patientBindInputVO.getPatientIdent();
        String hospitalNumber = patientBindInputVO.getHospitalNumber();

//        BPatient yxPatientPO = bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
//        if (yxPatientPO == null) {
//            throw new BizException("该病人不存在");
//        }

        List<BDevBind> yxDevBindPOList = bDevBindMapper.selectListByPatIdent(patientIdent);
        List<PatientBindOutputVO> patientBindOutputVOList = yxDevBindPOList.stream().map(yxDevBindPO -> {
            PatientBindOutputVO patientBindOutputVO = new PatientBindOutputVO();
            BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
            if(null!=yxDevDetailPO){
                patientBindOutputVO.setDevCode(yxDevDetailPO.getDevCode());
                patientBindOutputVO.setDevType(yxDevDetailPO.getDevType());
                patientBindOutputVO.setBrandTypeCode(yxDevDetailPO.getBrandTypeCode());
                patientBindOutputVO.setId(yxDevDetailPO.getId());

                BEquipmentBrand yxEquipmentBrandPO=bEquipmentBrandMapper.selectById(Long.valueOf(yxDevDetailPO.getBrand()));
                patientBindOutputVO.setBrandName(yxEquipmentBrandPO.getBrandName());
            }

            return patientBindOutputVO;
        }).collect(Collectors.toList());
        return patientBindOutputVOList;
    }

    @Override
    public List<PatientBindOutputVO> queryPatientBindHome(PatientBindInputVO patientBindInputVO) {
        String patientIdent = patientBindInputVO.getPatientIdent();
        String hospitalNumber = patientBindInputVO.getHospitalNumber();


        List<BDevBind> yxDevBindPOList = bDevBindMapper.selectListByPatIdent(patientIdent);
        List<PatientBindOutputVO> patientBindOutputVOList = yxDevBindPOList.stream().map(yxDevBindPO -> {
            PatientBindOutputVO patientBindOutputVO = new PatientBindOutputVO();
           int count= bDevDetailMapper.getCountByDevCode(yxDevBindPO.getDevCode());
            BDevDetail yxDevDetailPO ;
            if(count>1){
                List<BDevDetail> list=bDevDetailMapper.selectListByDevCode(yxDevBindPO.getDevCode());
                yxDevDetailPO=list.get(0);
           }else{
                yxDevDetailPO= bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
           }

            if(null!=yxDevDetailPO){
                patientBindOutputVO.setDevCode(yxDevDetailPO.getDevCode());
                patientBindOutputVO.setDevType(yxDevDetailPO.getDevType());
                patientBindOutputVO.setBrandTypeCode(yxDevDetailPO.getBrandTypeCode());
                patientBindOutputVO.setId(yxDevDetailPO.getId());

                BEquipmentBrand yxEquipmentBrandPO=bEquipmentBrandMapper.selectById(Long.valueOf(yxDevDetailPO.getBrand()));
                patientBindOutputVO.setBrandName(yxEquipmentBrandPO.getBrandName());
            }

            return patientBindOutputVO;
        }).collect(Collectors.toList());
        return patientBindOutputVOList;
    }

    @Override
    public List<PatientBindOutputVO> queryPatientBind(String hospitalNumber) {


        BPatient yxPatientPO = bPatientMapper.selectOneByHospitalNumber(hospitalNumber);
        if (yxPatientPO == null) {
            throw new BizException("该病人不存在");
        }

        List<BDevBind> yxDevBindPOList = bDevBindMapper.selectListByPatIdent(yxPatientPO.getPatientIdent());
        List<PatientBindOutputVO> patientBindOutputVOList = yxDevBindPOList.stream().map(yxDevBindPO -> {
            PatientBindOutputVO patientBindOutputVO = new PatientBindOutputVO();
            BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
            if(null!=yxDevDetailPO){
                patientBindOutputVO.setDevCode(yxDevDetailPO.getDevCode());
                patientBindOutputVO.setDevType(yxDevDetailPO.getDevType());
                patientBindOutputVO.setBrandTypeCode(yxDevDetailPO.getBrandTypeCode());
                patientBindOutputVO.setId(yxDevDetailPO.getId());

                BEquipmentBrand yxEquipmentBrandPO=bEquipmentBrandMapper.selectById(Long.valueOf(yxDevDetailPO.getBrand()));
                patientBindOutputVO.setBrandName(yxEquipmentBrandPO.getBrandName());
            }

            return patientBindOutputVO;
        }).collect(Collectors.toList());
        return patientBindOutputVOList;
    }

    @Override
    public BPatient selectPatientByDevCode(String devCode) {
        BPatient bPatient =null;
        BDevBind bDevBind = bDevBindMapper.selectBindByDevCode(devCode);
        if(null!=bDevBind){
            bPatient= bPatientMapper.selectOneByPatIdent(bDevBind.getPatientIdent());
        }
        return bPatient;
    }

    @Override
    public List<PatientBindOutputVO> queryPatientBindByPatiens(List<String> patients) {


        List<BDevBind> yxDevBindPOList = bDevBindMapper.selectListByPatIdents(patients);
        List<PatientBindOutputVO> patientBindOutputVOList = yxDevBindPOList.stream().map(yxDevBindPO -> {
            PatientBindOutputVO patientBindOutputVO = new PatientBindOutputVO();
            BDevDetail yxDevDetailPO = bDevDetailMapper.selectOneByDevCode(yxDevBindPO.getDevCode());
            if(null!=yxDevDetailPO){
                patientBindOutputVO.setDevCode(yxDevDetailPO.getDevCode());
                patientBindOutputVO.setDevType(yxDevDetailPO.getDevType());
                patientBindOutputVO.setBrandTypeCode(yxDevDetailPO.getBrandTypeCode());
                patientBindOutputVO.setId(yxDevDetailPO.getId());

                BEquipmentBrand yxEquipmentBrandPO=bEquipmentBrandMapper.selectById(Long.valueOf(yxDevDetailPO.getBrand()));
                patientBindOutputVO.setBrandName(yxEquipmentBrandPO.getBrandName());
            }

            return patientBindOutputVO;
        }).collect(Collectors.toList());
        return patientBindOutputVOList;
    }
}


